home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / nasanets.zip / NETIO.C < prev    next >
C/C++ Source or Header  |  1990-06-07  |  20KB  |  569 lines

  1. /*=============================*/
  2. /*           NETS              */
  3. /*                             */
  4. /* a product of the AI Section */
  5. /* NASA, Johnson Space Center  */
  6. /*                             */
  7. /* principal author:           */
  8. /*       Paul Baffes           */
  9. /*                             */
  10. /* contributing authors:       */
  11. /*      Bryan Dulock           */
  12. /*      Chris Ortiz            */
  13. /*=============================*/
  14.  
  15.  
  16. /*
  17. ----------------------------------------------------------------------
  18.   Code For Standard IO prompting routines (Prefix = IO_)
  19. ----------------------------------------------------------------------
  20.   This code is divided into 3 major sections:
  21.  
  22.   (1) include files
  23.   (2) global variables
  24.   (3) subroutines
  25.  
  26.   Each section is further explained below.
  27. ----------------------------------------------------------------------
  28. */
  29.  
  30.  
  31. /*
  32. ----------------------------------------------------------------------
  33.   INCLUDE FILES
  34. ----------------------------------------------------------------------
  35. */
  36. #include "common.h"
  37. #include "netio.h"
  38.  
  39.  
  40. /*
  41. ----------------------------------------------------------------------
  42.   GLOBAL VARIABLES
  43. ----------------------------------------------------------------------
  44.   The first global value below is a temporary work string needed by
  45.   almost all of the "my_get..." routines. This string is read in by
  46.   gets and then scanned for whatever the particular routines is looking
  47.   for. Following this are three global variables which contain the default
  48.   file names for the net's configuration, io pairs, and final weights
  49.   are declared here. These are NOT STATIC, so that they may be referenced
  50.   as EXTERN variables by other files.
  51.   7-3-89 I added the "buf_str" buffer for doing output in a more general
  52.   way (see IO_print). The idea is to provide a string which all files
  53.   can use for doing output.
  54. ----------------------------------------------------------------------
  55. */
  56. static char    in_string[MAX_LINE_SIZE];  /* used for 'my' IO routines   */
  57.                                           /* and IO_get_float_from_file  */
  58. char           IO_str[MAX_LINE_SIZE];     /* two strings for output      */
  59. char           IO_wkstr[MAX_LINE_SIZE];
  60. char           net_config[MAX_WORD_SIZE]; /* These are also referenced   */
  61. char           net_iop[MAX_WORD_SIZE];    /* outside, in netmain.c and   */
  62. char           net_fwt[MAX_WORD_SIZE];    /* net.c (see doc netmain.c)   */
  63. char           net_pwt[MAX_WORD_SIZE];    /* also (see IO_set_filenames) */
  64. static         int  more_counter;         /* # lines IO_more has printed */
  65.  
  66.  
  67. /*
  68. ======================================================================
  69.   ROUTINES IN NETIO.C                                                   
  70. ======================================================================
  71.   The routines in this file are grouped below by function.  Each routine
  72.   is prefixed by the string "IO_" indicating that it is defined in the 
  73.   "netio.c" file.  The types returned by the routines are also shown 
  74.   here so that cross checking is more easily done between these functions
  75.   and the other files which intern them.
  76.  
  77.  
  78.   Type Returned                 Routine                                 
  79.   -------------                 -------                                 
  80.     void                        IO_print                         
  81.     void                        IO_insert_format                        
  82.     void                        IO_update_str
  83.     int                         IO_reset_more
  84.     int                         IO_more                         
  85.     float                       IO_my_get_float                         
  86.     float                       IO_get_default_float                         
  87.     int                         IO_my_get_int
  88.     int                         IO_get_default_int
  89.     int                         IO_get_num_cycles
  90.     void                        IO_my_get_string (returns string via args)
  91.     void                        IO_set_filenames
  92.     long                        IO_find_file_size
  93.     void                        IO_get_io_name
  94.     void                        IO_get_wts_name
  95. ======================================================================
  96. */
  97.  
  98.  
  99. void  IO_print(target)
  100. int    target;
  101. /*
  102. ----------------------------------------------------------------------
  103.   This routine is the main routing routine for all output from the 
  104.   program. In anticipation of a variety of interfaces, I have included
  105.   a "target" variable which indicates the location to which the string
  106.   should be printed (eg, a window).
  107.   Note that this window defaults to printing the contents of the global
  108.   variable "IO_str" which is visible to all files expressly for the 
  109.   purpose of doing output.
  110. ----------------------------------------------------------------------
  111. */
  112. BEGIN
  113.    printf("%s", IO_str);
  114.    
  115. END /* IO_print */
  116.  
  117.  
  118. void  IO_insert_format(str)
  119. char  str[];
  120. /*
  121. ----------------------------------------------------------------------
  122.   After adding the option to compile with either floating point or
  123.   Sints (release 2.0), I realized that I would have different precision
  124.   for my floating point numbers depending on the format chosen. Sint
  125.   format yields only 3 decimal points of precision whereas floating
  126.   point can yield 6 (and sometimes more). Thus, all my %7.3f floating
  127.   point format statements for printf had to be changed! 
  128.   To effect the change, I decided to replace all floating point formats
  129.   with the string "%.f" which looks like a blank format. Then, this
  130.   routine is called to insert the proper numbers before and after the
  131.   period. That way, I can format the string generically, without 
  132.   worrying about floats or Sints.
  133. ----------------------------------------------------------------------
  134. */
  135. BEGIN
  136.    int   i,j,k;
  137.    void  IO_update_str();
  138.    
  139.    i = 0;
  140.    /*---------------------------------------*/
  141.    /* look for all occurrences of "%.f" and */
  142.    /* call update to insert the numbers     */
  143.    /*---------------------------------------*/
  144.    while (str[i] != '\0') BEGIN
  145.       if ((str[i] == '%') && (str[i+1] == '.') && (str[i+2] == 'f'))
  146.          IO_update_str(str, i);
  147.       i++;
  148.    ENDWHILE
  149.    
  150. END /* IO_insert_format */
  151.  
  152.  
  153. void  IO_update_str(str, loc)
  154. char  str[];
  155. int   loc;
  156. /*
  157. ----------------------------------------------------------------------
  158.   Once a string has been found with a "%.f" substring, this routine is
  159.   called to insert numbers before and after the period. The numbers 
  160.   inserted depend upon whether Sints or floats are being used. Sints
  161.   yield only 3 decimal points of precision, thus the formatting is 
  162.   "%7.3f" meaning a field 7 wide, with three places after the decimal.
  163.   (remember the Sint can be as large as 31 and can be positive or 
  164.   negative). Floats can yield up to 6 points of precision, thus their
  165.   format is "%10.6f" (ie, a field 3 wider and 3 more points of precision).
  166. ----------------------------------------------------------------------
  167. */
  168. BEGIN
  169.    static char  save[80];
  170.    int   i, j;
  171.    
  172.    /*------------------------------------------------*/
  173.    /* first save off everything after the "f" in str */
  174.    /*------------------------------------------------*/
  175.    i = loc+3;
  176.    j = 0;
  177.    while (str[i] != '\0')
  178.       save[j++] = str[i++];
  179.    save[j] = '\0';
  180.    
  181.    /*----------------------------------------*/
  182.    /* now insert the proper format note that */
  183.    /* "j" is also set for copying info back  */
  184.    /* from the save string.                  */
  185.    /*----------------------------------------*/
  186. #if  USE_SCALED_INTS
  187.    str[loc+1] = '7';
  188.    str[loc+2] = '.';
  189.    str[loc+3] = '3';
  190.    str[loc+4] = 'f';
  191.    j = loc+5;
  192. #else
  193.    str[loc+1] = '1';
  194.    str[loc+2] = '0';
  195.    str[loc+3] = '.';
  196.    str[loc+4] = '6';
  197.    str[loc+5] = 'f';
  198.    j = loc+6;
  199. #endif
  200.  
  201.    /*-------------------------------------------*/
  202.    /* copy everything back from the save string */
  203.    /*-------------------------------------------*/
  204.    i = 0;
  205.    while (save[i] != '\0')
  206.       str[j++] = save[i++];
  207.    str[j] = '\0';
  208.    
  209. END /* IO_update_str */
  210.  
  211.  
  212. void  IO_reset_more()
  213. /*
  214. ----------------------------------------------------------------------
  215.   Resets the number of lines that more has printed back to zero. This
  216.   procedure should be called before using procedures which call IO_more.
  217. ----------------------------------------------------------------------
  218. */
  219. BEGIN
  220.    more_counter = 0;
  221.    
  222. END /* IO_reset_more */
  223.  
  224.  
  225. int  IO_more(target)
  226. int  target;
  227. /*
  228. ----------------------------------------------------------------------
  229.  This procedure uses the common interface IO_print. The procedure will
  230.  wait and ask the user to enter Y/N after MAX_DISPLAY lines have been
  231.  displayed.
  232. ----------------------------------------------------------------------
  233. */
  234. BEGIN
  235.    int i,status;
  236.    char response[10];
  237.  
  238.    status = OK;
  239.    IO_print (target);
  240.    for ( i=0; i<= strlen ( IO_str ); i++ )
  241.       if ( IO_str[i] == '\n' ) more_counter ++;
  242.    
  243.    if (more_counter >= MAX_DISPLAY) BEGIN
  244.       more_counter = 0;
  245.  
  246.       sprintf(IO_str, "-------------- Continue ? (Y/N) --------------");
  247.       IO_print(target);
  248.       
  249.       fgets(response,10, stdin);
  250.       if ( response[0] == 'N' || response[0] == 'n' ) status = ERROR;
  251.    ENDIF
  252.    
  253.    return(status);
  254.    
  255. END /* IO_more */
  256.  
  257.  
  258. float  IO_my_get_float()
  259. /*
  260. ----------------------------------------------------------------------
  261.  Just a little routine, used often, for getting a floating number     
  262.   input from the screen.  It loops until it gets the float.           
  263. ----------------------------------------------------------------------
  264. */
  265. BEGIN
  266.    float  num;
  267.  
  268.    while (TRUE) BEGIN
  269.       if ( (gets(in_string) != NULL)
  270.            && (sscanf(in_string, "%f", &num) == 1) )
  271.          break;
  272.       else BEGIN
  273.          sprintf(IO_str, "\n   sorry, I don't understand.  Try again: ");
  274.          IO_print(0);
  275.       ENDELSE
  276.    ENDWHILE
  277.    return(num);
  278.  
  279. END /* IO_my_get_float */
  280.  
  281.  
  282. float  IO_get_default_float(default_num)
  283. float  default_num;
  284. /*
  285. ----------------------------------------------------------------------
  286.  This float-getting routine takes a default value which it returns if
  287.   the user does not type an floating point value.
  288. ----------------------------------------------------------------------
  289. */
  290. BEGIN
  291.    float  num;
  292.  
  293.    while (TRUE) BEGIN
  294.       gets(in_string);
  295.       if (in_string[0] == ENDSTRING)
  296.          return(default_num);
  297.       if (sscanf(in_string, "%f", &num) == 1)
  298.          return(num);
  299.       else BEGIN
  300.          sprintf(IO_str, "\n   sorry, I don't understand.  Try again: ");
  301.          IO_print(0);
  302.       ENDELSE
  303.    ENDWHILE
  304.  
  305. END /* IO_get_default_float */
  306.  
  307.  
  308. int  IO_my_get_int()
  309. /*
  310. ----------------------------------------------------------------------
  311.  Just a little routine, used often, for getting an integer input from 
  312.   the screen.  It loops until it gets the int.                        
  313. ----------------------------------------------------------------------
  314. */
  315. BEGIN
  316.    int  num;
  317.  
  318.    while (TRUE) BEGIN
  319.       if ( (gets(in_string) != NULL)
  320.            && (sscanf(in_string, "%d", &num) == 1) )
  321.          break;
  322.       else BEGIN
  323.          sprintf(IO_str, "\n   sorry, I don't understand.  Try again: ");
  324.          IO_print(0);
  325.       ENDELSE
  326.    ENDWHILE
  327.    return(num);
  328.  
  329. END /* IO_my_get_int */
  330.  
  331.  
  332. int  IO_get_default_int(default_int)
  333. int  default_int;
  334. /*
  335. ----------------------------------------------------------------------
  336.  This integer-getting routine takes a default value which it returns if
  337.   the user does not type an integer value.
  338. ----------------------------------------------------------------------
  339. */
  340. BEGIN
  341.    int  num;
  342.  
  343.    while (TRUE) BEGIN
  344.       gets(in_string);
  345.       if (in_string[0] == ENDSTRING)
  346.          return(default_int);
  347.       if (sscanf(in_string, "%d", &num) == 1)
  348.          return(num);
  349.       else BEGIN
  350.          sprintf(IO_str, "\n   sorry, I don't understand.  Try again: ");
  351.          IO_print(0);
  352.       ENDELSE
  353.    ENDWHILE
  354.  
  355. END /* IO_get_default_int */
  356.  
  357.  
  358. int  IO_get_num_cycles()
  359. /*
  360. ----------------------------------------------------------------------
  361.   This routine is used only during the "t" option of the main loop
  362.   (see netmain.c) and reads the desired number of cycles.
  363. ----------------------------------------------------------------------
  364. */
  365. BEGIN
  366.    int  num;
  367.  
  368.    if (gets(in_string) != NULL)
  369.       if (sscanf(in_string, "%d", &num) == 1)
  370.          return(num);
  371.    else
  372.       return(MAX_CYCLES);
  373.  
  374. END /* IO_get_num_cycles */
  375.  
  376.  
  377. void  IO_my_get_string(the_string)
  378. char  *the_string;
  379. /*
  380. ----------------------------------------------------------------------
  381.  Like the two routines above, this guy serves to get input from the   
  382.   terminal, in this case a string.  This routine is somewhat different
  383.   though, in that it requires that the place holder for the string be 
  384.   PASSED IN, rather than creating a result locally which is returned. 
  385. ----------------------------------------------------------------------
  386. */
  387. BEGIN
  388.    while (gets(the_string) == NULL) BEGIN
  389.       sprintf(IO_str, "\n     sorry, I don't understand.  Try again: ");
  390.       IO_print(0);
  391.    ENDWHILE
  392.  
  393. END /* IO_my_get_string */
  394.  
  395.  
  396. void  IO_set_filenames()
  397. /*
  398. ----------------------------------------------------------------------
  399.  This routine prompts the user for the name of the file containing    
  400.   the configuration specifics for the net to be created.  From that   
  401.   name, several default file names are computed and stored into       
  402.   gloabal strings.  These defaults then become options for filenames  
  403.   which will hold input and output information.                       
  404.  Assuming an input of the form "name.ext" the following defaults are  
  405.   generated:                                                          
  406.                                                                       
  407.      filename                      function                           
  408.      --------                      --------                           
  409.      name.iop                      holds the input/output pairs to be 
  410.                                      in training the net              
  411.      name.wts                      holds the weights for the net; ie, 
  412.                                      after training all the resultant 
  413.                                      weights would be stored here     
  414. ----------------------------------------------------------------------
  415.  I made a change to the naming conventions here (8-17-89) due to the
  416.   addition of PORTABLE weights files. That is, since a user may now 
  417.   store weights in two formats, I wanted the naming conventions to 
  418.   reflect that fact. I settled on the following two:
  419.   
  420.      name.fwt                      holds weights for a network saved
  421.                                      in FAST_FORMAT (see N_save_wts).
  422.      name.pwt                      holds the weights for a newtork
  423.                                      saved in PORTABLE_FORMAT.
  424.                                      
  425.   Note that these two filenames REPLACE the "name.wts" file.
  426. ----------------------------------------------------------------------
  427. */
  428. BEGIN
  429.    void  IO_my_get_string();
  430.    int   i;
  431.  
  432.    sprintf(IO_str, "\n   Enter filename with net configuration: ");
  433.    IO_print(0);
  434.    IO_my_get_string(net_config);
  435.  
  436.    strcpy(net_iop, net_config);
  437.    strcpy(net_fwt, net_config);
  438.    strcpy(net_pwt, net_config);
  439.    
  440.    for (i = 0; i < MAX_WORD_SIZE; i++)
  441.       if (net_config[i] == '.') break;
  442.    
  443.    if (i > (MAX_WORD_SIZE - 5)) BEGIN       /* If filename+ext too long */
  444.       net_iop[MAX_WORD_SIZE - 5] = '.';     /* ext are 3 chars, so a '.'*/
  445.       net_fwt[MAX_WORD_SIZE - 5] = '.';     /* must occur before the    */
  446.       net_pwt[MAX_WORD_SIZE - 5] = '.';     /* last 3 chars at least!   */
  447.       i = MAX_WORD_SIZE - 4;                /* So (3 + '.' + '\0') = 5  */
  448.    ENDIF                               
  449.  
  450.    else                                     /* if no problem, just incr */
  451.       i++;                                  /* i past the period        */
  452.  
  453.    net_iop[i]   = 'i';
  454.    net_iop[i+1] = 'o';
  455.    net_iop[i+2] = 'p';
  456.    net_iop[i+3] = ENDSTRING;
  457.    net_fwt[i]   = 'f';
  458.    net_fwt[i+1] = 'w';
  459.    net_fwt[i+2] = 't';
  460.    net_fwt[i+3] = ENDSTRING;
  461.    net_pwt[i]   = 'p';
  462.    net_pwt[i+1] = 'w';
  463.    net_pwt[i+2] = 't';
  464.    net_pwt[i+3] = ENDSTRING;
  465.  
  466. END /* IO_set_filenames */
  467.  
  468.  
  469. long  IO_find_file_size(filename)
  470. char  *filename;
  471. /*
  472. ----------------------------------------------------------------------
  473.  All this routine does is open up a file and find its length in bytes.
  474.  If the file can't be opened, then a length of 0 is returned.
  475. ----------------------------------------------------------------------
  476. */
  477. BEGIN
  478.    FILE  *fp;
  479.    long  length;
  480.    
  481.    fp = NULL;
  482.    
  483.    /*----------------------------------------*/
  484.    /* first, open the file "filename" and    */
  485.    /* if there is an error quit, returning 0 */
  486.    /*----------------------------------------*/
  487.    if ( (fp = fopen(filename, "rb")) == NULL )
  488.       return(0L);
  489.  
  490.    /*--------------------------------------------*/
  491.    /* otherwise, seek the end of the file. Note  */
  492.    /* that the zero here is an offset and the 2  */
  493.    /* indicates that end-of-file is sought (see  */
  494.    /* "fseek" documentation. Thus we are looking */
  495.    /* for the position 0 bytes from the end of   */
  496.    /* the file.                                  */   
  497.    /*--------------------------------------------*/
  498.    fseek(fp, 0L, 2);
  499.    
  500.    /*--------------------------------------------*/
  501.    /* use ftell to indicate the current position */
  502.    /* of the file pointer, in bytes, from the    */
  503.    /* beginning of the file.                     */
  504.    /*--------------------------------------------*/
  505.    length = ftell(fp);
  506.    
  507.    fclose(fp);
  508.    return(length);
  509.    
  510. END /* IO_find_file_size */
  511.  
  512.  
  513. void  IO_get_io_name()
  514. /*
  515. ----------------------------------------------------------------------
  516.  This routine prompts the user for the name of the file containing    
  517.   list of io pairs to be used in training the net.  A default name is 
  518.   printed out using the first part of the name given the last time    
  519.   the "set_filenames" routine above was called.  The user may either  
  520.   default to the name printed out (currently in net_iop) or he/she    
  521.   may enter a new name (which then becomes the default).              
  522. ----------------------------------------------------------------------
  523. */
  524. BEGIN
  525.    void  IO_my_get_string();
  526.    char  temp_str[MAX_WORD_SIZE];
  527.  
  528.    sprintf(IO_str, "\n   Enter name of file containing I/O pairs ");
  529.    IO_print(0);
  530.    sprintf(IO_str, "(default=%s): ", net_iop);
  531.    IO_print(0);
  532.    IO_my_get_string(temp_str);
  533.  
  534.    if (temp_str[0] != ENDSTRING)
  535.       strcpy(net_iop, temp_str);
  536.  
  537. END /* IO_get_io_name */
  538.  
  539.  
  540. void  IO_get_wts_name(format)
  541. int  format;
  542. /*
  543. ----------------------------------------------------------------------
  544.  This routine prompts the user for the name of the file containing    
  545.   list of io pairs to be used in training the net.  A default name is 
  546.   printed out using the first part of the name given the last time    
  547.   the "set_filenames" routine above was called.  The user may either  
  548.   default to the name printed out (currently in net_iop) or he/she    
  549.   may enter a new name (which then becomes the default).              
  550. ----------------------------------------------------------------------
  551.  (8-17-89) I added a parameter to this routine so that the correct 
  552. ----------------------------------------------------------------------
  553. */
  554. BEGIN
  555.    void  IO_my_get_string();
  556.    char  temp_str[MAX_WORD_SIZE];
  557.  
  558.    sprintf(IO_str, "(default=%s): ", ((format == FAST_FORMAT) ? net_fwt : net_pwt) );
  559.    IO_print(0);
  560.    IO_my_get_string(temp_str);
  561.  
  562.    if (temp_str[0] != ENDSTRING) BEGIN
  563.       if (format == FAST_FORMAT)
  564.          strcpy(net_fwt, temp_str);
  565.       else strcpy(net_pwt, temp_str);
  566.    ENDIF
  567.  
  568. END /* IO_get_wts_name */
  569.